package com.lis.scf.security;

import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 * Spring Security配置类
 */
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
@RequiredArgsConstructor
public class SecurityConfig {

//    private final CustomUserDetailsService userDetailsService;
    private final LoginSuccessHandler loginSuccessHandler;
    private final LoginFailureHandler loginFailureHandler;

    private final UserDetailsService userDetailsService;
    private final JwtAuthenticationFilter jwtAuthenticationFilter;
    private final JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;




    /**
     * 认证提供者
     */

//    @Bean
//    public DaoAuthenticationProvider authenticationProvider() {
//        DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
//        authProvider.setUserDetailsService(userDetailsService);
//        authProvider.setPasswordEncoder(passwordEncoder());
//        return authProvider;
//    }

    /**
     * 密码加密器
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * 认证管理器
     */
    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authConfig) throws Exception {
        return authConfig.getAuthenticationManager();
    }



    /**
     * 安全过滤链配置
     */
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
                .csrf().disable()  // 前后端分离架构下禁用CSRF
                .sessionManagement()
                    .sessionCreationPolicy(SessionCreationPolicy.STATELESS)  // 无状态会话
                    .and()
                .authorizeRequests()
                    // 允许匿名访问的接口
                    .antMatchers("/api/auth/login", "/api/auth/register", "/api/auth/sms-code").permitAll()
                    // 允许Swagger文档访问
                    .antMatchers("/swagger-ui/**", "/v3/api-docs/**").permitAll()
                    // 允许匿名访问的接口
//                    .antMatchers("/auth/login", "/auth/register","/auth/test", "/auth/send-code").permitAll()
                    // 其他接口需要认证
                    .anyRequest().authenticated()
                    .and()

                // 表单登录配置
                .formLogin()
                    .loginProcessingUrl("/auth/login")  // 登录接口
                    .successHandler(loginSuccessHandler)  // 登录成功处理器
                    .failureHandler(loginFailureHandler)  // 登录失败处理器
                    .permitAll()
                    .and()
                // 注销配置
                .logout()
                    .logoutUrl("/auth/logout")
                    .permitAll();

        // 设置认证提供者
        // 添加JWT过滤器（必须在UsernamePasswordAuthenticationFilter之前）
//        http.authenticationProvider(authenticationProvider());
        http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
        http.exceptionHandling()
                .authenticationEntryPoint(jwtAuthenticationEntryPoint); // 注册认证失败处理器
        return http.build();
    }
}
